package org.wkk.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.wkk.feignclients.ProductClient;

import java.util.List;

@RestController
public class UserController {

    private static final Logger log = LoggerFactory.getLogger(UserController.class);

    private DiscoveryClient discoveryClient;   //服务发现客户端
    private LoadBalancerClient loadBalancerClient;  //负载均衡客户端组件

    private RestTemplate restTemplate;    //这个对象才是具有负载均衡restTemplate

    private ProductClient productClient;

    @Autowired
    public UserController(DiscoveryClient discoveryClient, LoadBalancerClient loadBalancerClient, RestTemplate restTemplate, ProductClient productClient) {
        this.discoveryClient = discoveryClient;
        this.loadBalancerClient = loadBalancerClient;
        this.restTemplate = restTemplate;
        this.productClient = productClient;
    }


    //推荐http rest方式通信: 1.restTemplate
    @GetMapping("/invoke")
    public String invokeProduct() {
        log.info("调用用户服务...");
        //调用商品服务 缺点: 1.无法实现请求负载均衡  2.路径写死代码中不利于后续维护
        String result = new RestTemplate().getForObject("http://localhost:8002/product?id=21", String.class);
        log.info("商品服务调用结果: {}", result);
        return result;
    }


    //1.引入ribbon依赖(nacos client 存在这个依赖) 2.使用ribbon完成负载均衡  DiscoveryClient  LoadBalanceClient  @LoadBalance
    //DiscoveryClient
    @GetMapping("/discoveryClientInvoke")
    public String discoveryClientInvokeProduct() {
        log.info("调用用户服务...");
        List<ServiceInstance> serviceInstances = discoveryClient.getInstances("PRODUCTS");
        for (ServiceInstance serviceInstance : serviceInstances) {
            log.info("服务主机:{} 服务端口:{} 服务uri:{}", serviceInstance.getHost(), serviceInstance.getPort(), serviceInstance.getUri());
        }
        //discoveryClient需要自己做负载均衡
        String result = new RestTemplate().getForObject(serviceInstances.get(0).getUri() + "/product?id=21", String.class);

        return result;
    }

    //1.引入ribbon依赖(nacos client 存在这个依赖) 2.使用ribbon完成负载均衡  DiscoveryClient  LoadBalanceClient  @LoadBalance
    //LoadBalanceClient
    @GetMapping("/loadBalanceClientInvoke")
    public String loadBalanceClientInvokeProduct() {
        log.info("调用用户服务...");
        ServiceInstance serviceInstance = loadBalancerClient.choose("PRODUCTS");
        //discoveryClient需要自己做负载均衡
        String result = new RestTemplate().getForObject(serviceInstance.getUri() + "/product?id=21", String.class);
        return result;
    }

    //1.引入ribbon依赖(nacos client 存在这个依赖) 2.使用ribbon完成负载均衡  DiscoveryClient  LoadBalanceClient  @LoadBalance
    //@LoadBalance  让restTemplate具有负载均衡的功能
    @GetMapping("/loadBalanceInvoke")
    public String loadBalanceInvokeProduct() {
        log.info("调用用户服务...");
        String result = this.restTemplate.getForObject("http://PRODUCTS/product?id=21", String.class);
        log.info("商品服务调用结果: {}", result);
        return result;
    }

    //使用OpenFeign(伪httpcliet)进行服务间的调用
    @GetMapping("/openFeignInvoke")
    public String openFeignInvokeProduct() {
        log.info("调用用户服务...");
        String result = productClient.product(21);
        log.info("商品服务调用结果: {}", result);
        return result;
    }

}
